package com.aaron.client;

import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeItem;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.Widget;

import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.xml.client.*;

import java.util.*;

/**
 * @author aaron
 * 
 */
public class ProjectTree extends Composite {
	
	private class ClickableTreeItem extends Composite{
		private String path;
		private Image icon;
		private Hyperlink text;
		public ClickableTreeItem(String icon_path, String title, String path){
			this.path=path;
			//FocusPanel focus_panel=new FocusPanel();
			FlowPanel panel=new FlowPanel();
			icon=new Image(icon_path);
			icon.addStyleName("inline");
			text=new Hyperlink(title, path);
			text.addStyleName("inline");
			//text.addClickListener(callback);
			panel.add(icon);
			panel.add(text);
			//focus_panel.add(panel);
			//focus_panel.addClickListener(callback);
			initWidget(panel);
		}
		
		public String getPath(){
			return path;
		}
		public void setDirty(boolean dirty){
			if(dirty){
				text.addStyleName("italics");
				this.addStyleName("italics");
			}
			else{
				text.removeStyleName("italics");
				this.removeStyleName("italics");
			}
		}
	}
	private class NonClickableTreeItem extends Composite{
		private String path;
		private Image icon;
		private Label text;
		public NonClickableTreeItem(String icon_path, String title, String path){
			this.path=path;
			//FocusPanel focus_panel=new FocusPanel();
			FlowPanel panel=new FlowPanel();
			icon=new Image(icon_path);
			icon.addStyleName("inline");
			text=new Label(title);
			text.addStyleName("inline");
			//text.addClickListener(callback);
			panel.add(icon);
			panel.add(text);
			//focus_panel.add(panel);
			//focus_panel.addClickListener(callback);
			initWidget(panel);
		}
		
		public String getPath(){
			return path;
		}
		public void setDirty(boolean dirty){
			if(dirty){
				text.addStyleName("italics");
				this.addStyleName("italics");
			}
			else{
				text.removeStyleName("italics");
				this.removeStyleName("italics");
			}
		}
	}
	
	private Tree tree = new Tree();
	private String project_name;
	private String auth;

	public ProjectTree(String project_name, String auth) {
		initWidget(tree);
		setStyleName("vivcode-ProjectManager");
		this.project_name=project_name;
		this.auth=auth;
		this.refresh();
	}

	public void refresh() {
		//get project tree as xml
		SubversionServiceAsync subversion_service =SubversionService.Util.getInstance();
		subversion_service.getTreeXML(project_name, auth, 
		new AsyncCallback(){
			public void onSuccess(Object result) {
				com.google.gwt.xml.client.Document document=XMLParser.parse((String)result);
				TreeItem root=buildTree(document.getDocumentElement());
				tree.clear();
				tree.addItem(root);
			}

			public void onFailure(Throwable caught) {
				RootPanel.get().add(new Label("Unable to login:"));
				RootPanel.get().add(new Label("Message:"+caught.getMessage()));
				RootPanel.get().add(new Label("Stack Trace:"));
				StackTraceElement[] trace=caught.getStackTrace();
				for(int i=0; i<trace.length; i++){
					RootPanel.get().add(new Label(trace[i].getMethodName()+" at "+trace[i].getFileName()+":"+trace[i].getLineNumber()));
				}
				RootPanel.get().add(new Label("To String:"+caught.toString()));
			}
		});
	}
	public void setSelectedDirty(){
		TreeItem item=tree.getSelectedItem();
		ClickableTreeItem clickable_item=(ClickableTreeItem)item.getWidget();
		clickable_item.setDirty(true);
	}
	public void setSelectedClean(){
		TreeItem item=tree.getSelectedItem();
		ClickableTreeItem clickable_item=(ClickableTreeItem)item.getWidget();
		clickable_item.setDirty(false);
	}
	public void setAllClean(){
		Iterator itr=this.tree.iterator();
		while(itr.hasNext()){
			Object obj=itr.next();
			if(obj instanceof ClickableTreeItem){
				ClickableTreeItem item=(ClickableTreeItem)obj;
				item.setDirty(false);
			}
		}
	}
	private  TreeItem buildTree(Element element){
		//Window.alert("buildTree() called");
		String type=element.getNodeName();
		String name=element.getAttribute("name");
		String path=element.getAttribute("path");
		String icon_path="";
		if(type=="Folder"){
			icon_path="icons/folder.png";
		}
		else if(type=="File"){
			String extension=getExtension(element.getAttribute("name"));
			if(extension=="c" || extension=="cc"){
				icon_path="icons/page_white_c.png";
			}
			else if(extension=="h"){
				icon_path="icons/page_white_h.png";
			}
			else if(extension=="cpp" || extension=="hpp"){
				icon_path="icons/page_white_cplusplus.png";
			}
			else if(extension=="cs" ){
				icon_path="icons/page_white_csharp.png";
			}
			else if(extension=="php" ){
				icon_path="icons/page_white_php.png";
			}
			else if(extension=="rb" ){
				icon_path="icons/page_white_ruby.png";
			}
			else if(extension=="java" ){
				icon_path="icons/page_white_cup.png";
			}
			else{
				icon_path="icons/page_white.png";
			}
		}
		class ChangeHistoryClickListener implements ClickListener{
			private String path;
			public ChangeHistoryClickListener(String path){
				this.path=path;
			}
			public void onClick(Widget sender){
				History.newItem(path);
			}
		}
		TreeItem tree_item=null;
		if(type=="File"){
			tree_item=new TreeItem(new ClickableTreeItem(icon_path, name, path));
		}
		if(type=="Folder"){
			tree_item=new TreeItem(new NonClickableTreeItem(icon_path, name, path));
		}
		

		//Window.alert("buildTree() element:name="+element.getAttribute("name"));
		int length = element.getChildNodes().getLength();
		//Window.alert("buildTree() : child nodes:"+length);
		for(int i=0; i<length; i++){
			if(element.getChildNodes().item(i).getNodeType()==Node.ELEMENT_NODE){
				Element child = (Element)element.getChildNodes().item(i);
				tree_item.addItem(buildTree(child));
			}
		}
		//Window.alert("buildTree() returned");
		return tree_item;
	}
	/**
	   * Generates HTML for a tree item with an attached icon.
	   * 
	   * @param imageUrl the url of the icon image
	   * @param title the title of the item
	   * @return the resultant HTML
	   */
	  private static String imageItemHTML(String imageUrl, String title) {
	    return "<span><img style='margin-right:4px' src='" + imageUrl.toLowerCase()
	        + "'>" + title + "</span>";
	  }
	private static native String getExtension(String name)/*-{
		if(name.indexOf(".")!=-1){
			return name.substr(name.indexOf(".")+1);
		}
		else{
			return "";
		}
	}-*/;
}
